package cs301.msflags;

import java.io.Serializable;
import java.util.Vector;

import android.content.Intent;
import android.graphics.Point;
import cs301.game.GameAction;
import cs301.game.GameComputerPlayer;
import cs301.game.GamePlayer;

/**
 * @author John Olennikov
 * @author Kyanne Mayfield
 * @author Allie Seibert
 * @author Emilia Holbik
 * @version 12/7/2012
 * 
 *           This class is the smart AI, which knows how to play the game and
 *           plays it with a random algorithm for flagging and uncovering.
 */

public class MSFlagsSimpleComputerPlayer extends GameComputerPlayer {

	/**
	 * A reference to my copy of the current game state
	 */
	
	private MSFlagsGame myMSFlagsGame = null;

	/**
	 * the source of the ai player, which is always 1
	 */

	private int aiPlayer;

	/**
	 * Initializes SimpleComputerPlayer
	 */

	public MSFlagsSimpleComputerPlayer() {
		super();
	}

	/**
	 * Start the "configure game" activity
	 */
	public void startSetupActivity() {
		Intent setupIntent = new Intent(MSFlagsSimpleComputerPlayer.this,
				MSFlagsSetupActivity.class);

		// Return true if myMSFlagsGame is created
		Boolean isGameCreated = (myMSFlagsGame != null);

		setupIntent.putExtra("isGameCreated", isGameCreated);

		// Random (150) intent id
		startActivityForResult(setupIntent, 150);

		// Prevents animation when switching activities
		overridePendingTransition(0, 0);
	}

	/**
	 * Gets the user specified board dimensions and number of mines from the
	 * configure board screen, and gives it to the gamestate to reconfigure the
	 * board.
	 * 
	 * @param requestCode  indicates where the activity result came from
	 * @param resultCode  the result code from the activity
	 * @param data  an intent containing the information obtained by the
	 *            activity
	 */
	@Override
	public void onActivityResult(int requestCode, int resultCode, Intent data) {
		// extract the game state
		myMSFlagsGame = (MSFlagsGame) this.game;

		MSFlagsMainActivity.showConfig = false;

		if (!data.getBooleanExtra("resumeGame", false)) {

			int boardWidth = data.getIntExtra("boardWidth", 20);
			int boardHeight = data.getIntExtra("boardHeight", 20);
			int totalNumMines = data.getIntExtra("totalNumMines", 15);

			// Return this resulting action to the caller
			Intent intent = this.getIntent();
			intent.putExtra(GamePlayer.GAME_ACTION,
					(Serializable) new MSFlagsConfigureBoardAction(
							myMSFlagsGame.whoseTurn(), boardWidth, boardHeight,
							totalNumMines));
			setResult(RESULT_OK, intent);
			finish();
		}
	}

	/**
	 * The first time this method is called it uncovers a mine, any successive
	 * calls have 50/50 chance of flagging a random space or ending the turn.
	 * 
	 * @return  the action with which to update the game state and change the 
	 *          turn to the next player
	 */

	@Override
	protected GameAction calculateMove() {
		aiPlayer = this.game.whoseTurn();
		
		//get the board object and the board space object
		Board myBoardObject = (Board) ((MSFlagsGame) this.game).getBoard();
		BoardSpace[][] board = myBoardObject.getBoardSpaceArray();
		boolean isTurn = true;
		boolean hasFlag = false;
		
		// determine how many flags the AI still has left to flag
		int flagsRemaining = ((MSFlagsGame) this.game)
				.getFlagsRemaining(aiPlayer);
		Vector<Point> coveredSpaces = new Vector<Point>();
		
		// iterate through the board, adding the covered spaces to a vector
		for (int x = 0; x < board.length; x++) {
			for (int y = 0; y < board[0].length; y++) {
				if (board[x][y].isCovered() && !board[x][y].isFlagged()) {
					coveredSpaces.add(new Point(x, y));
				}

			}
		}
		
		// if all spaces have been covered, add a dummy point
		if (coveredSpaces.isEmpty()) {
			for (int x = 0; x < board.length; x++) {
				for (int y = 0; y < board[0].length; y++) {
					if (board[x][y].isCovered()) {
						coveredSpaces.add(new Point(x, y));
					}
				}
			}
		}
		
		// generate a random point from covered spaces which to uncover
		Point temp = coveredSpaces.elementAt((int) (Math.random()
				* coveredSpaces.size() - 1));
		myBoardObject.uncoverSpace(temp.x, temp.y);
		coveredSpaces.remove(temp);
		if (coveredSpaces.isEmpty()) {
			isTurn = false;
		}
		
		while (isTurn) {
			// with a probability of 0.5, flag a space
			if (Math.random() < .5) {
				hasFlag = flagsRemaining > 0;
				temp = coveredSpaces.elementAt((int) (Math.random()
						* coveredSpaces.size() - 1));
				// update the number of flags remaining
				flagsRemaining += myBoardObject.flaggedByPlayer(aiPlayer,
						hasFlag, temp.x, temp.y);
			} else {
				isTurn = false;
			}
		}
		// after flagging and uncovering, end the AI's turn
		return new MSFlagsEndTurnAction(aiPlayer, myBoardObject,
				flagsRemaining, myBoardObject.getUncoveredMine());
	}

	@Override
	protected boolean needConfig() {
		Board myBoardObject = (Board) ((MSFlagsGame) this.game).getBoard();
		return (myBoardObject == null);
	}

	@Override
	protected void doConfig() {
		startSetupActivity();

	}
}